using UnityEngine;
using System.Collections;


public class WeaponBehaviour : Equipable
{
    public enum States
    {
        CanShoot,
        Shoot,
        Empty,
        Idle,
    }
#region Members
    public WeaponTemplate m_Template;
    public int m_loadedAmmo;
    public int m_spareAmmo;
    public States m_State = States.Idle;
    float m_Timer = 0;
    public float m_ReloadTimer = 0;

    //Se usan para saber si estas manteniendo o no.
    public bool pressed;
    bool pressedPrev = false;
    public bool m_RapidFire = false;
    public bool m_InfiniteBullets = false;

    float m_EquipTime = 0;
    bool m_FinishedEquipping = false;

    //Para saber si el arma es de un jugador o de un enemigo
    //public bool PlayerWeapon = false;
    int m_LayerToIgnore = 0;
#endregion


    public WeaponBehaviour(WeaponTemplate t, int layer)
    {
        this.m_Template = t;
        m_UseRange = m_Template.Range;
        m_loadedAmmo = t.capacityMagazine;
        m_RapidFire = t.RapidFire;

        m_LayerToIgnore = 1 << 2;
        m_LayerToIgnore += 1 << 9;
        m_LayerToIgnore += 1 << 10;
        m_LayerToIgnore += 1 << 11;
        m_LayerToIgnore += 1 << layer;
    }
    public override void Update()
    {
        if (m_FinishedEquipping)
        {
            if (m_State == States.Idle)
            {
                m_Timer += Time.deltaTime;
                if (m_Timer >= m_Template.fireRate)
                {
                    m_State = States.CanShoot;
                }
            }
            else if (m_State == States.Empty)
            {
                //Debug.Log("ta empty");
            }
            pressedPrev = pressed;
            pressed = false;
        }
        else
        {
            m_Timer += Time.deltaTime;
            if (m_Timer >= m_EquipTime)
            {
                m_Timer = 0;
                m_FinishedEquipping = true;
            }
        }
    }
    public void Reload(Bullets bullets)
    {
        int toReload = m_Template.capacityMagazine - m_loadedAmmo;
        if (toReload >= bullets.m_BulletAmount)
        {
            m_loadedAmmo += bullets.m_BulletAmount;
            bullets.m_BulletAmount = 0;
            m_State = States.Idle;
        }
        else
        {
            m_loadedAmmo += toReload;
            bullets.m_BulletAmount -= toReload;
            m_State = States.Idle;
        }
    }
    /// <summary>
    /// Se llama al equiparse/cambiar a esta arma.
    /// </summary>
    public override void OnEquip(Actor owner)
    {
        m_Timer = m_Template.fireRate; //asi puede disparar de una
        m_ReloadTimer = 0;
        if(owner is Character)
        {
            m_EquipTime = m_Template.equipTime * ((Character)owner).m_CharacterData.attributes.GetSubAttributeMaxValue(SUB_ATTRIBUTES.EQUIP_TIME);
            m_FinishedEquipping = false;
        }
        else
        {
            m_FinishedEquipping = true;
        }
    }
    private bool shootingActor = false;
    public override void Use(Actor targetActor, Actor owner)
    {
        shootingActor = true;
        Use(targetActor.transform.position, owner);
        shootingActor = false;
    }
    public override void Use(Vector3 targetPos, Actor owner)
    {
        if (m_FinishedEquipping == false) return;
        pressed = true;
        if(Vector3.Distance(targetPos,owner.GetMountingPoint()) >= m_UseRange)
        {
            Debug.Log("out of range to shoot");
            SoundManager.Instance.PlaySound("No",true);
            return;
        }
        if (Shoot())
        {
            SoundManager.Instance.PlaySound(m_Template.SoundName,targetPos);
            Vector3 raydirection;
            //por un tema del character controller si le estoy disparando a un personaje tengo q hacer esto.
            if (shootingActor)
            {
                raydirection = (targetPos + Vector3.up) - owner.GetMountingPoint();
            }
            else
            {
                raydirection = targetPos - owner.GetMountingPoint();
            }
            Ray ray = new Ray(owner.GetMountingPoint(), raydirection);
            RaycastHit raycastHitInfo;
            if (Physics.Raycast(ray, out raycastHitInfo, m_UseRange * 2.0f, ~(m_LayerToIgnore)))
            {
                Actor a = raycastHitInfo.transform.GetComponent<Actor>();
                if (a != null)
                {
                    a.OnHit(m_Template.damage, owner);
                }
                else
                {
                    HittableObject ho = raycastHitInfo.transform.GetComponent<HittableObject>();
                    if (ho != null)
                    {
                        ho.OnHit(m_Template.damage);
                    }
                    //Debug.Log("Disparo en el piso/pared, falta efecto visual");
                }
                MakeSound(owner,owner.transform.position);
                //GameObject.Instantiate(GameManager.GetInstance().ShootParticle, raycastHitInfo.point, Quaternion.identity);
                GameObject go = PrefabManager.GetInstance().CreateFromPool("shooteffect");
                if (go != null)
                {
                    go.transform.position = raycastHitInfo.point;
                }
            }
            else
            {
                Debug.LogWarning("El rayo del disparo no choco con nada");
            }
        }
        else
        {
            //Debug.Log("Can't Shoot");
        }
    }

    /// <summary>
    /// Se fija si puede disparar y hace la logica que tiene que hacer en caso de hacerlo.
    /// </summary>
    /// <returns>Devuelve si dispara</returns>
    public bool Shoot()
    {
        if (m_State == States.Empty)
        {
            SoundManager.Instance.PlaySound("Empty");
        }
        if (m_State != States.CanShoot) return false;

        if (m_RapidFire)
        {
            m_State = States.Shoot;
        }
        else if (!pressedPrev)
        {
            m_State = States.Shoot;
        }

        if (m_State == States.Shoot)
        {
            if (m_loadedAmmo <= 0)
            {

                //Debug.Log("Reload Start");
                m_State = States.Empty;
            }
            else
            {
                m_Timer = 0;
                if (m_InfiniteBullets == false)
                {
                    m_loadedAmmo--;
                }
                m_State = States.Idle;
                return true;
            }
        }
        return false;
    }
    /// <summary>
    /// Hace ruido que escuchan los enemigos solo si el que dispara es un character.
    /// </summary>
    /// <param name="owner">El que disparo</param>
    /// <param name="soundPosition">De donde sale el sonido</param>
    void MakeSound(Actor owner, Vector3 soundPosition)
    {
        if ((owner is Character) == false) return;
        VisionManager.GetInstance().GenerateSound(soundPosition, m_Template.Noise);
    }
}